home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Games / Tetris / Source / ScoreKeeper.m < prev    next >
Text File  |  1993-07-10  |  5KB  |  249 lines

  1.  
  2. #import <defaults/defaults.h>
  3. #import <appkit/Matrix.h>
  4. #import <appkit/TextField.h>
  5. #import <appkit/TextFieldCell.h>
  6. #import <appkit/Window.h>
  7. #import <pwd.h>
  8. #import <strings.h>
  9. #import <sys/types.h>
  10. #import <ctype.h>
  11. #import "ScoreKeeper.h"
  12. #import "TetApp.h"
  13.  
  14. #define SCORE_FILE    ".TetrisScores"
  15.  
  16. #define NUM_SCORES    10
  17. #define BEZEL_SIZE    2.0
  18. #define FIELD_X_OFFSET    2.0
  19.  
  20. extern void setpwent();
  21. extern void endpwent();
  22. extern uid_t getuid();
  23. extern void chmod(char *path, int mode);
  24.  
  25. @implementation ScoreKeeper
  26. #ifdef FOO
  27. - (int) fileFoundProc(char *)path
  28. {
  29.     strcpy(self->path, path);
  30.     return 0;
  31. }
  32. #endif
  33.  
  34. - (NXStream *)findScoresFile:(int) mode
  35. {
  36.     NXStream *result;
  37.     char *appName;
  38.     
  39.     strcpy(path, NXArgv[0]);
  40.     if ((appName = rindex(path, '/')))
  41.       appName++;
  42.     else 
  43.       appName = path;
  44.     strcpy(appName, SCORE_FILE);
  45.     if (!(result = NXMapFile(path, mode))) {
  46.         strcat(strcat(strcpy(path, NXHomeDirectory()), "/"), SCORE_FILE);
  47.         result = (mode == NX_READONLY) ? NXMapFile(path, NX_READONLY) :
  48.         NXOpenMemory(NULL, 0, mode);
  49.     }
  50.     return result;
  51. }
  52.  
  53. - init
  54. {
  55.     [super init];
  56.     nameField = nil;
  57.     return self;
  58. }
  59.  
  60. - (void) readHighScores:(NXStream *)stream
  61. {
  62.     int c;
  63.     char name[BUFSIZ];
  64.     char level[5];
  65.     char myScore[10];
  66.     
  67.     for (c = 0; c < NUM_SCORES; c++) {
  68.         name[0] = level[0] = myScore[0] = '\0';
  69.         NXScanf(stream, "%[^\7]\7%[^\7]\7%[^\7]\7", name, level, myScore);
  70.         [[names cellAt:c :0] setStringValue:name],
  71.         [[levels cellAt:c :0] setStringValue:level],
  72.         [[scores cellAt:c :0] setStringValue:myScore];
  73.     }
  74. }
  75.  
  76. - setScoresWindow:anObject
  77. {
  78.     NXStream *inStream;
  79.     
  80.     scoresWindow = anObject;
  81.     [scoresWindow setDelegate:self];
  82.     if ((inStream = [self findScoresFile: NX_READONLY])) {
  83.         [self readHighScores: inStream];
  84.         NXCloseMemory(inStream, NX_FREEBUFFER);
  85.     }
  86.     return self;
  87. }
  88.  
  89. - setZero
  90. {
  91.     [score setIntValue:0];
  92.     return self;
  93. }
  94.  
  95. - addScore:(int)amount
  96. {
  97.     [score setIntValue:[score intValue] + amount];
  98.     return self;
  99. }
  100.  
  101. static char *username()
  102. {
  103.     static char *username = (char *)0;
  104.     struct passwd *pwdentry;
  105.     static char ubuf [128];
  106.     
  107.     if (!username) {
  108.         char * pc;
  109.  
  110.         setpwent();
  111.         pwdentry = getpwuid(getuid());
  112.         endpwent();
  113.         username = ((pwdentry) ? pwdentry->pw_gecos : "");
  114.         /* extended GECOS field handling added by Detlev Droege,
  115.         * droege@infko.uni-koblenz.de, December 1991 */
  116.         if (pc = index (username, ','))
  117.           *pc = 0;        /* strip ','-part of gecos field */
  118.         if (index (username, '&')) {
  119.             /* do '&' expansion */
  120.             pc = ubuf;
  121.             while (*username) {
  122.                 if (*username == '&') {
  123.                     strcpy (pc, pwdentry->pw_name);
  124.                     *pc = toupper (*pc);
  125.                     while (*pc) pc++;
  126.                 }
  127.                 else
  128.                   *pc++ = *username;
  129.                 username++;
  130.             }
  131.             *pc = 0;
  132.             username = ubuf;
  133.         }
  134.     }
  135.     return username;
  136. }
  137.  
  138. - (int) findrank:(int) myScore
  139. {
  140.     id window = [names window];
  141.     int myRank;
  142.     int c;
  143.  
  144.     [window disableFlushWindow];
  145.     for (myRank = 0; myRank < NUM_SCORES; myRank++)
  146.       if (myScore >= [[scores cellAt:myRank :0] intValue])
  147.          break;
  148.     for (c = NUM_SCORES - 1; c > myRank; c--) {
  149.         [[names cellAt:c :0] setStringValue:
  150.          [[names cellAt:(c - 1) :0] stringValue]];
  151.  
  152.         [[levels cellAt:c :0] setStringValue:
  153.          [[levels cellAt:(c - 1) :0] stringValue]];
  154.  
  155.         [[scores cellAt:c :0] setStringValue:
  156.          [[scores cellAt:(c - 1) :0] stringValue]];
  157.     }
  158.     [window reenableFlushWindow];
  159.     return myRank;
  160. }
  161.  
  162. - updateHighScores:(int)level
  163. {
  164.     id window = [names window];
  165.     int scoreValue = [score intValue];
  166.     NXRect nRect;
  167.     
  168.     if ((rank = [self findrank: scoreValue]) < NUM_SCORES) {
  169.         [scoresWindow makeKeyAndOrderFront:self];
  170.         [[levels cellAt:rank :0] setIntValue:level];
  171.         [[scores cellAt:rank :0] setIntValue:scoreValue];
  172.         [[names getCellFrame:&nRect at:rank :0] convertRect:&nRect toView:nil];
  173.         NXInsetRect(&nRect, -BEZEL_SIZE, -BEZEL_SIZE);
  174.         nRect.origin.x -= FIELD_X_OFFSET;
  175.  
  176.         if (!nameField) {
  177.             nameField = [[TextField alloc] initFrame:&nRect];
  178.             [nameField setEditable:YES];
  179.             [[nameField setTarget:self] setAction:@selector(nameFieldEnd:)];
  180.         } else
  181.           [nameField moveTo:nRect.origin.x :nRect.origin.y];
  182.  
  183.         [nameField setStringValue:username()];
  184.         [[window contentView] addSubview:nameField];
  185.         [[nameField display] selectText:self];
  186.         while ([NXApp peekAndGetNextEvent:NX_KEYUPMASK | NX_KEYDOWNMASK]) ;
  187.         [NXApp runModalFor:window];
  188.     }
  189.     return self;
  190. }
  191.  
  192. - nameFieldEnd:sender
  193. {
  194.     id window = [names window];
  195.     
  196.     [window disableFlushWindow];
  197.     [[names cellAt:rank :0] setStringValue:[nameField stringValue]];
  198.     [nameField removeFromSuperview];
  199.     [window display];
  200.     [[window reenableFlushWindow] flushWindow];
  201.     [NXApp stopModal];
  202.     return self;
  203. }
  204.  
  205. - windowWillClose:sender
  206. {
  207.     if (nameField && [nameField currentEditor]) {
  208.         [self nameFieldEnd:sender];
  209.         return nil;
  210.     } else
  211.       return self;
  212. }
  213.  
  214. - writeHighScores:(NXStream *)stream
  215. {
  216.     int c;
  217.     
  218.     for (c = 0; c < NUM_SCORES; c++)
  219.         NXPrintf(stream, "%s\7%s\7%s\7",
  220.                     [[names cellAt:c :0] stringValue],
  221.                     [[levels cellAt:c :0] stringValue],
  222.                     [[scores cellAt:c :0] stringValue]);
  223.     NXFlush(stream);
  224.      return self;
  225. }
  226.  
  227. - writeScores
  228. {
  229.     NXStream *outStream;
  230.  
  231.     if ((outStream = [self findScoresFile: NX_WRITEONLY])) {
  232.         [self writeHighScores: outStream];
  233.         NXSaveToFile(outStream, path);
  234.         NXCloseMemory(outStream, NX_FREEBUFFER);
  235.         chmod(path, 0666);
  236.     }
  237.     return self;
  238. }
  239.  
  240. - free
  241. {
  242.     if (nameField)
  243.         [nameField free];
  244.     return [super free];
  245. }
  246.  
  247. @end
  248.  
  249.